package com.lmk.mkcc.service.impl;

import com.lmk.mkcc.CourseDoc;
import com.lmk.mkcc.config.HighlightResultMapper;
import com.lmk.mkcc.dto.CourseEsDto;
import com.lmk.mkcc.repository.CourseEsRepository;
import com.lmk.mkcc.result.EsAggrPageList;
import com.lmk.mkcc.result.PageList;
import com.lmk.mkcc.service.ISearchService;
import com.lmk.mkcc.vo.AggrTermsBucketVo;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SearchServiceImpl implements ISearchService {
    @Autowired
    private CourseEsRepository courseEsRepository;
    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    @Override
    public void add(CourseDoc courseDoc) {

        courseEsRepository.save(courseDoc);
    }

    @Override
    public void delect(Long id) {
        courseEsRepository.deleteById(id);
    }

    @Override
    public PageList<CourseDoc> getCourseEs(CourseEsDto courseEsDto) {
        String keyword = courseEsDto.getKeyword();
        String gradeName = courseEsDto.getGradeName();
        Long courseTypeId = courseEsDto.getCourseTypeId();
        Double priceMax = courseEsDto.getPriceMax();
        Double priceMin = courseEsDto.getPriceMin();
        String sortField = courseEsDto.getSortField();
        String sortType = courseEsDto.getSortType();
        String chargeName = courseEsDto.getChargeName();

        // 高亮操作
        HighlightResultMapper highlightResultMapper = new HighlightResultMapper();

        // 1.创建条件构造器
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 2.根据关键字i进行查询
        if (StringUtils.isNotEmpty(keyword)){// 关键字分词查询，使用must，模糊查询
            boolQueryBuilder.must(QueryBuilders.matchQuery("name", keyword));
        }
        if (StringUtils.isNotEmpty(chargeName)){
            boolQueryBuilder.filter(QueryBuilders.termQuery("chargeName", chargeName));
        }
        if (StringUtils.isNotEmpty(gradeName)){
            boolQueryBuilder.filter(QueryBuilders.termQuery("gradeName", gradeName));
        }
        if (courseTypeId != null){
            boolQueryBuilder.filter(QueryBuilders.termQuery("courseTypeId", courseTypeId));
        }
        // 3.范围查询，使用range
        if (priceMax != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(priceMax));
        }
        if (priceMin != null){
            boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(priceMin));
        }
       // 4.排序
        if (StringUtils.isNotEmpty(sortField) && StringUtils.isNotEmpty(sortType)){
            SortOrder sortOrder = "asc".equalsIgnoreCase(sortType)? SortOrder.ASC:SortOrder.DESC;
            nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField).order(sortOrder));
        }
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        // 5.设置分页条件
        nativeSearchQueryBuilder.withPageable(PageRequest.of(courseEsDto.getPage()-1,
                                                            courseEsDto.getRows()));
        // 设置高亮
        nativeSearchQueryBuilder.withHighlightFields(new HighlightBuilder.Field("name").preTags("<span style='color:red'>").postTags("</span>"));

        // 聚合操作
        /*nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("gradeNameTermsAgg").field("gradeName"));
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("chargeNameTermsAgg").field("charge"));*/


        // 6.根据条件构造器创建条件对象
        NativeSearchQuery build = nativeSearchQueryBuilder.build();



        // 7.根据查询条件查询ES数据
        // 不做高亮操作：Page<CourseDoc> page = courseEsRepository.search(build);
        AggregatedPage<CourseDoc> courseDocs = elasticsearchRestTemplate.queryForPage(build, CourseDoc.class, highlightResultMapper);

        /*// 封装聚合结果
        Aggregations aggregations = courseDocs.getAggregations();

        Map<String, List<AggrTermsBucketVo>> aggrsMap = new HashMap<>();

        aggregations.asMap().entrySet().forEach(e->{
            List<AggrTermsBucketVo> aggrTermsBucketVos = new ArrayList<>();
            String key = e.getKey();
            ParsedStringTerms parsedStringTerms = (ParsedStringTerms) e.getValue();
            parsedStringTerms.getBuckets().forEach(p->{
                AggrTermsBucketVo aggrTermsBucketVo = new AggrTermsBucketVo();
                String keyAsString = p.getKeyAsString();
                long docCount = p.getDocCount();
                aggrTermsBucketVo.setKey(keyAsString);
                aggrTermsBucketVo.setDocCount(docCount);
                aggrTermsBucketVos.add(aggrTermsBucketVo);
            });
            aggrsMap.put(key, aggrTermsBucketVos);
        });*/



        // 返回分页数据
        return new PageList<>(courseDocs.getTotalElements(), courseDocs.getContent());
        /*return new EsAggrPageList<>(courseDocs.getTotalElements(), courseDocs.getContent(), aggrsMap);*/
    }
}
